﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using RookieLibSharp.Security;
namespace RookieLibSharp.Xml
{
    public class XmlManager
    {
        private string XmlFilePath = null;
#if DEBUG
#else
        private string XmlTempPath = null;
#endif
        private XmlDocument m_xmlDoc = null;
        private XmlNode m_nodeCurrent = null;
        private XmlNode m_nodeCursor = null;
        private string m_strSource = "";

        public XmlManager(string xmlFilePath)
        {
#if DEBUG
            XmlFilePath = xmlFilePath;
            LoadXml(XmlFilePath);
#else
            XmlFilePath = xmlFilePath;
            XmlTempPath = Path.GetTempFileName();
            string key = XmlFilePath;

            AES.DecryptFile(XmlFilePath, XmlTempPath);

            LoadXml(XmlTempPath);
#endif
        }
        public void Terminate()
        {
#if DEBUG
            SaveXml(XmlFilePath);
#else
            AES.EncryptFile(XmlTempPath, XmlFilePath);
            LibFunction.DeleteFile(XmlTempPath);
#endif
        }

        public String Source
        {
            set { m_strSource = value; }
        }

        public XmlNode Current
        {
            get { return m_nodeCurrent; }
            set { m_nodeCurrent = value; }
        }

        public XmlNode Cursor
        {
            get { return m_nodeCursor; }
            set { m_nodeCursor = value; }
        }

        public String XPath
        {
            set
            {
                if (m_nodeCurrent == null)
                {
                    m_nodeCursor = m_xmlDoc.SelectSingleNode(value);
                }
                else
                {
                    m_nodeCursor = m_nodeCurrent.SelectSingleNode(value);
                }
            }
        }

        public string Value
        {
            get
            {
                if (m_nodeCursor == null)
                {
                    return "";
                }
                else
                {
                    return ((m_nodeCursor.FirstChild != null) ? m_nodeCursor.FirstChild.Value : "");
                }
            }
            set
            {
                if (m_nodeCursor != null)
                {
                    if (m_nodeCursor.FirstChild == null)
                    {
                        m_nodeCursor.AppendChild(m_xmlDoc.CreateTextNode(value));
                    }
                    else
                    { 
                        m_nodeCursor.FirstChild.Value = value; 
                    }
                }
            }
        }

        public XmlNodeList Nodes
        {
            get { return m_xmlDoc.SelectNodes(m_strSource); }
        }

        public string getValue(string strXPath)
        {
            this.XPath = strXPath;
            return this.Value;
        }
        public void setValue(string strXPath, string strValue)
        {
            this.XPath = strXPath;
            this.Value = strValue;
        }

        private bool LoadXml(string filePath)
        {
            m_xmlDoc = new XmlDocument();
            try
            {
                m_xmlDoc.Load(filePath);
            }
            catch
            {
                return false;
            }
            return true;
        }

        public bool SaveXml(string filePath = null)
        {
            bool bRet = true;
            if (m_xmlDoc != null)
            {
                try
                {
                    if (null == filePath)
                    {
                        m_xmlDoc.Save(XmlFilePath);
                    }
                    else
                    {
                        m_xmlDoc.Save(filePath);
                    }
                    
                }
                catch
                {
                    bRet = false;
                }
            }
            return bRet;
        }

        // insert one node into the strXPath node before the nIndex sub item (maybe not the nIndex sub child)
        // return the added one
        public XmlNode InsertItem(XmlNode xml_insert, string strXPath, string strXPathChild, int nIndex, bool bReplace)
        {
            XmlNode xmlNew = xml_insert.Clone();
            XPath = strXPath;
            XmlNodeList xmlNodes = m_nodeCursor.SelectNodes(strXPathChild);
            try
            {
                if (bReplace)
                {
                    m_nodeCursor.ReplaceChild(xmlNew, xmlNodes[nIndex]);
                }
                else
                {
                    m_nodeCursor.InsertBefore(xmlNew, (nIndex == xmlNodes.Count ? null : xmlNodes[nIndex]));
                }
            }
            catch
            {
               
            }
            return xmlNew;
        }

        public XmlNode RemoveItem(string strXPath, string strXPathChild, int nIndex)
        {
            XPath = strXPath;
            XmlNodeList xmlNodes = m_nodeCursor.SelectNodes(strXPathChild);
            if (nIndex >= xmlNodes.Count)
            {
                return null;
            }
            return m_nodeCursor.RemoveChild(xmlNodes[nIndex]);
        }
        public XmlNode CreateNode(string name)
        {
            return m_xmlDoc.CreateElement(name);
        }
        public XmlAttribute CreateAttribute(string name)
        {
            return m_xmlDoc.CreateAttribute(name);
        }
        public XmlAttribute SetXmlNodeAttribute(XmlNode xmlNode, string name, string value)
        {
            XmlAttribute attribute = xmlNode.Attributes[name];
            if (null == attribute)
            {
                attribute = CreateAttribute(name);
                xmlNode.Attributes.Append(attribute);
            }
            attribute.Value = value;
            return attribute;
        }
        public XmlAttribute SetXmlNodeAttribute(XmlNode xmlNode, string name, int value)
        {
            return SetXmlNodeAttribute(xmlNode, name, value.ToString());
        }
        public XmlAttribute SetXmlNodeAttribute(XmlNode xmlNode, string name, double value)
        {
            return SetXmlNodeAttribute(xmlNode, name, value.ToString());
        }
        public string GetXmlNodeAttribute(XmlNode xmlNode, string name)
        {
            XmlAttribute attribute = xmlNode.Attributes[name];
            if (null == attribute)
            {
                return "";
            }
            return attribute.Value;
        }
        public XmlNode GetChildXmlNodeByName(XmlNode parentNode, string childNodeName)
        {
            string attr;
            for (int idx = 0; idx < parentNode.ChildNodes.Count;idx++ )
            {
                attr = GetXmlNodeAttribute(parentNode.ChildNodes[idx], "name");
                if (attr == childNodeName)
                {
                    return parentNode.ChildNodes[idx];
                }
            }
            return null;
        }
    }
}
